#include <mutex.h>
#include <memory.h>
#include <schedule.h>

#include <print.h>

static LIST MUTEX_LIST;         // 互斥锁链表


#include <task.h>
extern volatile TASK*          current_task;

/******************************************************************************
* 函数名称: void MutexInit(void)
* 功能说明: 初始化互斥锁
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 
******************************************************************************/
void MutexInit(void)
{
    ListInit(&MUTEX_LIST);
}

/******************************************************************************
* 函数名称: MUTEX* SYS_MutexCreat(void)
* 功能说明: 创建互斥锁
* 输入参数: 无
* 输出参数: 无
* 函数返回: MUTEX*          --互斥锁
* 其它说明: 
******************************************************************************/
MUTEX* SYS_MutexCreat(void)
{
    MUTEX* mutex = (MUTEX *)Malloc(sizeof(MUTEX));
    
    if(NULL == mutex)
        return NULL;

    mutex->lock = 0;                              // 可用状态
    ListAddHead(&MUTEX_LIST, (LIST_NODE *)mutex); // 头插
    QueueInit(&mutex->wait);                      // 初始化互斥锁中的等待队列

    return mutex;
}

/******************************************************************************
* 函数名称: static BOOL CheckMutex(MUTEX* mutex)
* 功能说明: 检查互斥锁是否合法有效
* 输入参数: MUTEX*          --互斥锁
* 输出参数: 无
* 函数返回: 0:无效; 1:有效
* 其它说明: 无
******************************************************************************/
static BOOL CheckMutex(MUTEX* mutex)
{
    LIST_NODE* pListNode = NULL;
    MUTEX* nodeTmp = NULL;

    LIST_FOR_EACH(&MUTEX_LIST, pListNode)
    {
        nodeTmp = (MUTEX *)LIST_NODE(pListNode, MUTEX, node);
        if(mutex == nodeTmp)
            return 1;
    }
    return 0;
} 

/******************************************************************************
* 函数名称: E_RET SYS_MutexLock(MUTEX* mutex)
* 功能说明: 上锁
* 输入参数: MUTEX* mutex    --互斥锁
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_MutexLock(MUTEX* mutex)
{
    // 检查参数合法性
    if(NULL == mutex || !CheckMutex(mutex))
        return E_ERR;
    
    // 如果互斥锁处于空闲状态，则将其上锁，否则，将当前任务放到等待队列中并立即切换到下一个任务
    if(0 == mutex->lock)
    {
        printk(" %s Lock\n", current_task->name);
        mutex->lock = 1;
    }
    else
    {
        printk(" %s enters the waiting queue\n", current_task->name);
        MutexSuspend(mutex);
    }
        
    return E_OK;
}

/******************************************************************************
* 函数名称: E_RET SYS_MutexLock(MUTEX* mutex)
* 功能说明: 解锁
* 输入参数: MUTEX* mutex    --互斥锁
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_MutexUnLock(MUTEX* mutex)
{
    // 检查参数合法性
    if(NULL == mutex || !CheckMutex(mutex))
        return E_ERR;

    // 将互斥锁设置为空闲可用状态，并将互斥锁等待队列中的任务放回到就绪队列中
    mutex->lock = 0;
    printk(" %s Unlock\n", current_task->name);
    MutexResume(mutex);

    return E_OK;
}

/******************************************************************************
* 函数名称: E_RET SYS_MutexLock(MUTEX* mutex)
* 功能说明: 销毁互斥锁
* 输入参数: MUTEX* mutex    --互斥锁
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_MutexDestory(MUTEX* mutex)
{
    // 检查参数合法性
    if(NULL == mutex || !CheckMutex(mutex))
        return E_ERR;

    // 删除链表节点并释放内存
    ListDelNode(&mutex->node);
    Free(mutex);

    return E_OK;
}